home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Libraries / TransSkel / Demos / C Demos / DialogSkel / DialogSkel.c next >
Encoding:
C/C++ Source or Header  |  1994-02-21  |  10.8 KB  |  530 lines  |  [TEXT/KAHL]

  1. /*
  2.  * When a modeless dialog goes inactive, the controls should be dimmed.
  3.  * But that can't be done without an event hook.  Ugh.  Another ugliness
  4.  * of not handling dialogs through the main event loop.
  5.  */
  6.  
  7. /*
  8.  * DialogSkel - TransSkel modeless dialog demonstration.
  9.  *
  10.  * 21 Apr 88 Version 1.00 Paul DuBois
  11.  * 29 Jan 89 Version 1.01
  12.  * - Conversion for TransSkel 2.0.
  13.  * 07 Jan 91 Version 1.02
  14.  * - Conversion for TransSkel 3.00.
  15.  * 05 Jun 93 Version 1.03
  16.  * - Fixed to compile under THINK C 6.0.
  17.  * 09 Oct 93
  18.  * - Catches suspend/resume events, hides/shows dialogs when these occur.
  19.  * 19 Nov 93
  20.  * - Does better job on suspend/resume.  Rather than using HideWindow() and
  21.  * ShowWindow(), uses ShowHide() to preserve stacking order.
  22.  * - Added regular document window to provide contrast in handling during
  23.  * suspend/resume and to provide a way to bring the application forward by
  24.  * clicking in a window.  (With just dialogs, all the windows are hidden
  25.  * on a suspend.)
  26.  * - Added menu hook to disable Edit menu items when document window is
  27.  * frontmost, since editing doesn't apply to it.
  28.  * - Added Close item to File menu.
  29.  * 09 Dec 93
  30.  * - Updated for TransSkel 3.05.
  31.  * - Flush mouse down on activate when document window wasn't frontmost
  32.  * to preserve stacking order.
  33.  * 30 Dec 93
  34.  * - Fixed bug where closing modeless window by clicking close box caused
  35.  * Visible checkbox to be unchecked in partner, but closing by selecting
  36.  * Close from File menu didn't.
  37.  * 31 Dec 93
  38.  * - Junked all the dialog item manipulation routines and replaced by calls
  39.  * to the equivalent routines that now make up part of the auxiliary
  40.  * component of TransSkel (these routines are new in TS 3.06).
  41.  * 18 Dec 93
  42.  * - Ditto for new 3.07 routines.
  43.  * 11 Feb 94
  44.  * - Minor revisions.
  45.  * 21 Feb 94
  46.  * - Updated for TransSkel 3.11.
  47.  */
  48.  
  49. # include    "TransSkel.h"
  50.  
  51.  
  52.  
  53. typedef enum            /* menu ID numbers */
  54. {
  55.     fileMenuID = skelAppleMenuID + 1,
  56.     editMenuID
  57. };
  58.  
  59.  
  60. typedef enum
  61. {
  62.     mDlogRes = 1000,
  63.     aboutAlrtRes,        /* About... alert resource number */
  64.     docWindRes = 1000
  65. };
  66.  
  67.  
  68. typedef enum            /* File menu item numbers */
  69. {
  70.     showDlog1 = 1,
  71.     showDlog2,
  72.     showDoc,
  73.     closeWind,
  74.     fGrayLine,
  75.     quit
  76. };
  77.  
  78.  
  79. typedef enum             /* Edit menu item numbers */
  80. {
  81.     undo = 1,
  82.     eGrayLine,
  83.     cut,
  84.     copy,
  85.     paste,
  86.     clear
  87. };
  88.  
  89.  
  90. typedef enum                /* dialog item numbers */
  91. {
  92.     button1 = 1,
  93.     edit1,
  94.     static1,
  95.     radio1,
  96.     radio2,
  97.     radio3,
  98.     check1,
  99.     check2,
  100.     user1
  101. };
  102.  
  103.  
  104. static DialogPtr    mDlog1;
  105. static DialogPtr    mDlog2;
  106. static WindowPtr    docWind;
  107. static short        iconNum1 = 0;
  108. static short        iconNum2 = 0;
  109.  
  110. static MenuHandle    fileMenu;
  111. static MenuHandle    editMenu;
  112.  
  113.  
  114. /* ------------------- */
  115. /* Miscellaneous stuff */
  116. /* ------------------- */
  117.  
  118.  
  119. static pascal void
  120. DrawIcon (DialogPtr dlog, short item)
  121. {
  122. Handle    h;
  123. Rect    r;
  124.  
  125.     SkelGetDlogRect (dlog, item, &r);
  126.     h = GetIcon (dlog == mDlog1 ? iconNum1 : iconNum2);
  127.     PlotIcon (&r, h);
  128. }
  129.  
  130.  
  131. static void
  132. SetDlogRadio (DialogPtr dlog, short item)
  133. {
  134. DialogPtr    partner;
  135. GrafPtr        tmpPort;
  136. Rect        r;
  137.  
  138.     partner = (DialogPtr) GetWRefCon (dlog);
  139.     SkelSetDlogRadioButtonSet (dlog, radio1, radio3, item);
  140.  
  141.     if (partner == mDlog1)
  142.         iconNum1 = item - radio1;
  143.     else
  144.         iconNum2 = item - radio1;
  145.  
  146.     SkelGetDlogRect (partner, user1, &r);
  147.     GetPort (&tmpPort);
  148.     SetPort (partner);
  149.     InvalRect (&r);    /* invalidate item rect to generate update event */
  150.     SetPort (tmpPort);
  151. }
  152.  
  153.  
  154. /* ---------------------------------------- */
  155. /* Dialog window setup and handler routines */
  156. /* ---------------------------------------- */
  157.  
  158.  
  159. static pascal void
  160. DlogEvent (short item, EventRecord *event)
  161. {
  162. DialogPtr    actor, partner;
  163. Str255        title;
  164. short        value;
  165.  
  166.     GetPort (&actor);
  167.     partner = (DialogPtr) GetWRefCon (actor);
  168.     switch (item)
  169.     {
  170.     case button1:
  171.         SkelGetDlogStr (actor, edit1, title);
  172.         SetWTitle (partner, title);
  173.         break;
  174.  
  175.     /* set radio buttons */
  176.  
  177.     case radio1:
  178.     case radio2:
  179.     case radio3:
  180.         SetDlogRadio (actor, item);
  181.         break;
  182.  
  183.     /* flip check boxes */
  184.  
  185.     case check1:
  186.         value = SkelToggleDlogCtlValue (actor, item);
  187.         if (value == 0)
  188.             HideWindow (partner);
  189.         else
  190.             ShowWindow (partner);
  191.         break;
  192.  
  193.     case check2:
  194.         value = SkelToggleDlogCtlValue (actor, item);
  195.         ((WindowPeek) partner)->goAwayFlag = (char) (value ? 255 : 0);
  196.         break;
  197.     }
  198. }
  199.  
  200.  
  201. static pascal void
  202. DlogClose (void)
  203. {
  204. DialogPtr    actor, partner;
  205.  
  206.     GetPort (&actor);
  207.     partner = (DialogPtr) GetWRefCon (actor);
  208.     HideWindow (actor);
  209.     SkelSetDlogCtlValue (partner, check1, 0);
  210. }
  211.  
  212.  
  213. static pascal void
  214. DlogClobber (void)
  215. {
  216. DialogPtr    dlog;
  217.  
  218.     GetPort (&dlog);
  219.     DisposeDialog (dlog);
  220. }
  221.  
  222.  
  223. static DialogPtr
  224. DemoDialog (StringPtr title, short h, short v)
  225. {
  226. DialogPtr    dlog;
  227.  
  228.     dlog = GetNewDialog (mDlogRes, nil, (WindowPtr) -1L);
  229.     MoveWindow (dlog, h, v, false);
  230.     SetWTitle (dlog, title);
  231.     (void) SkelDialog (dlog, DlogEvent, DlogClose, DlogClobber);
  232.     return (dlog);
  233. }
  234.  
  235.  
  236. /* ------------------------------------------ */
  237. /* Document window setup and handler routines */
  238. /* ------------------------------------------ */
  239.  
  240.  
  241. static pascal void
  242. DocUpdate (Boolean resized)
  243. {
  244. }
  245.  
  246.  
  247. static pascal void
  248. DocActivate (Boolean active)
  249. {
  250. }
  251.  
  252.  
  253. static pascal void
  254. DocClobber (void)
  255. {
  256.     HideWindow (docWind);
  257.     DisposeWindow (docWind);
  258. }
  259.  
  260.  
  261. static void
  262. DocWindow (short h, short v)
  263. {
  264.     if (SkelQuery (skelQHasColorQD))
  265.         docWind = GetNewCWindow (docWindRes, nil, (WindowPtr) -1L);
  266.     else
  267.         docWind = GetNewWindow (docWindRes, nil, (WindowPtr) -1L);
  268.     (void) SkelWindow (docWind, nil, nil, DocUpdate, DocActivate, nil,
  269.                     DocClobber, nil, false);
  270.     MoveWindow (docWind, h, v, false);
  271. }
  272.  
  273.  
  274. /* ------------- */
  275. /* Menu handlers */
  276. /* ------------- */
  277.  
  278.  
  279. /*
  280.  * Handle selection of About... item from Apple menu
  281.  */
  282.  
  283. static pascal void
  284. DoAppleMenu (short item)
  285. {
  286.     (void) SkelAlert (aboutAlrtRes, SkelDlogFilter (nil, true),
  287.                                             skelPositionOnParentDevice);
  288.     SkelRmveDlogFilter ();
  289. }
  290.  
  291.  
  292. /*
  293.  * File menu handler
  294.  */
  295.  
  296. static pascal void
  297. DoFileMenu (short item)
  298. {
  299.     switch (item)
  300.     {
  301.     case showDlog1:
  302.         SelectWindow (mDlog1);
  303.         ShowWindow (mDlog1);
  304.         SkelSetDlogCtlValue (mDlog2, check1, 1);
  305.         break;
  306.     
  307.     case showDlog2:
  308.         SelectWindow (mDlog2);
  309.         ShowWindow (mDlog2);
  310.         SkelSetDlogCtlValue (mDlog1, check1, 1);
  311.         break;
  312.     
  313.     case showDoc:
  314.         SelectWindow (docWind);
  315.         ShowWindow (docWind);
  316.         break;
  317.  
  318.     case closeWind:
  319.         SkelClose (FrontWindow ());
  320.         break;
  321.  
  322.     case quit:
  323.         SkelStopEventLoop ();
  324.         break;
  325.     }
  326. }
  327.  
  328.  
  329. /*
  330.  * Handle Edit menu
  331.  */
  332.  
  333. static pascal void
  334. DoEditMenu (short item)
  335. {
  336. DialogPtr    dlog;
  337.  
  338.     if (SystemEdit (item - 1))        /* if DA handled operation, return */
  339.         return;
  340.  
  341.     /* if front window is document window, do nothing */
  342.     dlog = (DialogPtr) FrontWindow ();
  343.     if (((WindowPeek) dlog)->windowKind != dialogKind)
  344.         return;
  345.  
  346.     switch (item)
  347.     {
  348.     case cut:
  349.         DlgCut (dlog);
  350.         (void) ZeroScrap ();
  351.         (void) TEToScrap ();
  352.         break;
  353.  
  354.     case copy:
  355.         DlgCopy (dlog);
  356.         (void) ZeroScrap ();
  357.         (void) TEToScrap ();
  358.         break;
  359.  
  360.     case paste:
  361.         (void) TEFromScrap ();
  362.         DlgPaste (dlog);
  363.         break;
  364.  
  365.     case clear:
  366.         DlgDelete (dlog);
  367.         break;
  368.     }
  369. }
  370.  
  371.  
  372. /*
  373.  * Adjust menus when mouse click occurs in menu bar, before
  374.  * menus are shown.
  375.  */
  376.  
  377. static pascal void
  378. AdjustMenus (void)
  379. {
  380. WindowPtr    w = FrontWindow ();
  381.  
  382.     if (w == (WindowPtr) nil)
  383.         DisableItem (fileMenu, closeWind);
  384.     else
  385.         EnableItem (fileMenu, closeWind);
  386.  
  387.     if (w == docWind)
  388.     {
  389.         DisableItem (editMenu, undo);
  390.         DisableItem (editMenu, cut);
  391.         DisableItem (editMenu, copy);
  392.         DisableItem (editMenu, paste);
  393.         DisableItem (editMenu, clear);
  394.     }
  395.     else
  396.     {
  397.         /* modeless dialog or DA -- dim undo for dialogs */
  398.         if (((WindowPeek) w)->windowKind == dialogKind)
  399.             DisableItem (editMenu, undo);
  400.         else
  401.             EnableItem (editMenu, undo);
  402.         EnableItem (editMenu, cut);
  403.         EnableItem (editMenu, copy);
  404.         EnableItem (editMenu, paste);
  405.         EnableItem (editMenu, clear);
  406.     }
  407. }
  408.  
  409.  
  410. /* ---------------------- */
  411. /* Suspend/resume handler */
  412. /* ---------------------- */
  413.  
  414.  
  415. /*
  416.  * On a suspend, hide the dialog windows and deactivate the frontmost window
  417.  * if there is one.  Normally the system will unhilite the front window, but
  418.  * since hiding the dialogs may cause the document window to be hilited, it's
  419.  * necessary to unhilite whatever window's frontmost after hiding the windows.
  420.  *
  421.  * Similarly, on an activate, the system may hilite the frontmost window, but
  422.  * but showing the dialogs may result in a new frontmost window, which then
  423.  * needs to be hilited.  If the document window was not frontmost when the
  424.  * suspend occurred, the system will also generate a mouse click to bring it
  425.  * forward.  To preserve the stacking order, suck the mouse click out of the
  426.  * event queue.
  427.  */
  428.  
  429. static pascal void
  430. SuspendResume (Boolean inForeground)
  431. {
  432. WindowPtr    w;
  433. EventRecord    event;
  434. static Boolean    hidden1;
  435. static Boolean    hidden2;
  436.  
  437.     if (!inForeground)
  438.     {
  439.         hidden1 = hidden2 = false;
  440.         if (((WindowPeek) mDlog1)->visible)
  441.         {
  442.             ShowHide (mDlog1, false);
  443.             hidden1 = true;
  444.         }
  445.         if (((WindowPeek) mDlog2)->visible)
  446.         {
  447.             ShowHide (mDlog2, false);
  448.             hidden2 = true;
  449.         }
  450.         if ((w = FrontWindow ()) != (WindowPtr) nil)
  451.         {
  452.             HiliteWindow (w, false);
  453.             SkelActivate (w, false);
  454.         }
  455.     }
  456.     else
  457.     {
  458.         if ((w = FrontWindow ()) != (WindowPtr) nil)
  459.             HiliteWindow (w, false);
  460.         if (hidden1)
  461.             ShowHide (mDlog1, true);
  462.         if (hidden2)
  463.             ShowHide (mDlog2, true);
  464.         if ((w = FrontWindow ()) != (WindowPtr) nil)
  465.         {
  466.             HiliteWindow (w, true);
  467.             SkelActivate (w, true);
  468.         }
  469.         if (EventAvail (mDownMask, &event))
  470.             (void) GetNextEvent (mDownMask, &event);
  471.     }
  472. }
  473.  
  474.  
  475. /* ------------ */
  476. /* Main program */
  477. /* ------------ */
  478.  
  479.  
  480. int
  481. main (void)
  482. {
  483.     SkelInit ((SkelInitParamsPtr) nil);
  484.  
  485.     SkelSetSuspendResume (SuspendResume);
  486.  
  487.     /* 311 = ellipsis */
  488.     SkelApple ((StringPtr) "\pAbout DialogSkel\311", DoAppleMenu);
  489.  
  490.     fileMenu = NewMenu (fileMenuID, (StringPtr) "\pFile");
  491.     AppendMenu (fileMenu, (StringPtr) "\pShow Dialog 1;Show Dialog 2;Show Doc Window");
  492.     AppendMenu (fileMenu, (StringPtr) "\pClose/W;(-;Quit/Q");
  493.     (void) SkelMenu (fileMenu, DoFileMenu, nil, false, false);
  494.  
  495.     editMenu = NewMenu (editMenuID, (StringPtr) "\pEdit");
  496.     AppendMenu (editMenu, (StringPtr) "\p(Undo/Z;(-;Cut/X;Copy/C;Paste/V;Clear");
  497.     (void) SkelMenu (editMenu, DoEditMenu, nil, false, false);
  498.     
  499.     DrawMenuBar ();
  500.     SkelSetMenuHook (AdjustMenus);
  501.     
  502.     DocWindow (100, 125);
  503.     
  504.     mDlog1 = DemoDialog ((StringPtr) "\pModeless Dialog 1", 50, 50);
  505.     mDlog2 = DemoDialog ((StringPtr) "\pModeless Dialog 2", 150, 200);
  506.     SetWRefCon (mDlog1, (long) mDlog2);
  507.     SetWRefCon (mDlog2, (long) mDlog1);
  508.     SkelSetDlogStr (mDlog1, edit1, (StringPtr) "\pModeless Dialog 2");
  509.     SkelSetDlogStr (mDlog2, edit1, (StringPtr) "\pModeless Dialog 1");
  510.     SkelSetDlogProc (mDlog1, user1, DrawIcon);
  511.     SkelSetDlogProc (mDlog2, user1, DrawIcon);
  512.     SkelSetDlogRadioButtonSet (mDlog1, radio1, radio3, radio1);
  513.     SkelSetDlogRadioButtonSet (mDlog2, radio1, radio3, radio1);
  514.     SkelSetDlogCtlValue (mDlog1, check1, 1);
  515.     SkelSetDlogCtlValue (mDlog2, check1, 1);
  516.     SkelSetDlogCtlValue (mDlog1, check2, 1);
  517.     SkelSetDlogCtlValue (mDlog2, check2, 1);
  518.  
  519.     SelectWindow (docWind);
  520.     ShowWindow (docWind);
  521.     SelectWindow (mDlog1);
  522.     ShowWindow (mDlog1);
  523.     SelectWindow (mDlog2);
  524.     ShowWindow (mDlog2);
  525.  
  526.     SkelEventLoop ();
  527.     SkelCleanup ();
  528. }
  529.  
  530.